// ============================================================================
//
// Copyright (C) 2006-2007 Dengues
//
// Google Group: http://groups.google.com/group/dengues
// QQ Group: 24885404
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ============================================================================
package org.dengues.ui.cdc;

import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.dengues.commons.connectivity.IConnectivitySettingsConstants;
import org.dengues.core.DenguesCorePlugin;
import org.dengues.core.ExceptionOperation;
import org.dengues.core.connectivity.IConnectivityManager;
import org.dengues.core.dbs.IChangeDataCaptureManager;
import org.dengues.core.metadata.MetadataHelper;
import org.dengues.core.metadata.types.MetadataTypesManager;
import org.dengues.model.DenguesModelManager;
import org.dengues.model.database.DBColumn;
import org.dengues.model.database.DBTable;
import org.dengues.model.database.DatabaseDiagram;
import org.dengues.model.project.CDCConnType;
import org.dengues.model.project.ConnPropertyAttriType;
import org.dengues.model.project.ConnPropertySetType;
import org.dengues.model.warehouse.ColumnType;
import org.dengues.model.warehouse.MetadataType;
import org.dengues.model.warehouse.WarehouseFactory;
import org.dengues.ui.prefs.connectivity.EConnectivityProperties;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.util.EList;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

/**
 * Qiang.Zhang.Adolf@gmail.com class global comment. Detailled comment <br/>
 * 
 * $Id: Dengues.epf Qiang.Zhang.Adolf@gmail.com 2008-5-4 qiang.zhang $
 * 
 */
public class ChangeDataCaptureManager implements IChangeDataCaptureManager {

    private ArrayList<String> pkList;

    private ArrayList<String> varsList;

    private ArrayList<String> noPKList;

    private boolean ok = false;

    private String msg = "Execute SQL Statement sucessfully.";

    private final ConnPropertySetType setType;

    private final String connId;

    private boolean pause = false;

    private boolean stop = false;

    /**
     * Qiang.Zhang.Adolf@gmail.com ChangeDataCaptureManager constructor comment.
     * 
     * @param setType
     */
    public ChangeDataCaptureManager(ConnPropertySetType setType) {
        this.setType = setType;
        String split = setType.getId().substring(IConnectivitySettingsConstants.PROP_DEFN.length() + 1);
        connId = split + IConnectivitySettingsConstants.CONNECTIVITY_DELIMITER + setType.getName();
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com ChangeDataCaptureManager constructor comment.
     * 
     * @param dbDiagram
     */
    public ChangeDataCaptureManager(DatabaseDiagram dbDiagram) {
        this.setType = MetadataHelper.getConnSetType(dbDiagram);
        connId = dbDiagram.getConnId();
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "exeSQLScript".
     * 
     * @param sql
     * @return
     */
    public boolean exeSQLScript(final String sql) {
        ProgressMonitorDialog pmd = new ProgressMonitorDialog(Display.getDefault().getActiveShell());
        try {
            pmd.run(true, true, new IRunnableWithProgress() {

                public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
                    monitor.beginTask("Execute Sql...", IProgressMonitor.UNKNOWN);
                    String sql2 = sql.replaceAll("\n", "");
                    sql2 = sql2.replaceAll("\r", "");
                    String[] str = sql.split(SQL_SEQ);
                    IConnectivityManager manager = DenguesCorePlugin.getDefault().getDenguesUiService().getConnectivityManager();
                    Properties props = new Properties();
                    EList<ConnPropertyAttriType> attributes = setType.getAttributes();
                    for (ConnPropertyAttriType attri : attributes) {
                        props.put(attri.getName(), attri.getValue());
                    }
                    manager.getConnection(props, false, false);
                    final String title = "Execute SQL Statement";
                    Statement createStatement = null;
                    String trim = null;
                    String substring = null;
                    try {
                        createStatement = manager.getConnection().createStatement();
                        for (String string : str) {
                            trim = string.trim();
                            int indexOf = trim.indexOf("\n");
                            substring = indexOf > -1 ? trim.substring(0, indexOf) + "..." : trim;
                            if (trim.length() > 0 && !"null".equals(trim.toLowerCase())) {
                                try {
                                    while (pause) {
                                        Thread.sleep(100);
                                    }
                                    if (stop) {
                                        break;
                                    }
                                    monitor.subTask(substring);
                                    if (trim.contains("INSERT INTO  ")) {
                                        createStatement.executeUpdate(trim);
                                    } else {
                                        createStatement.execute(trim);
                                    }
                                } catch (final Exception e) {
                                    pause = true;
                                    Display.getDefault().asyncExec(new Runnable() {

                                        public void run() {
                                            MessageDialog dialog = new MessageDialog(new Shell(), title, null, e.getMessage(),
                                                    MessageDialog.QUESTION, new String[] { IDialogConstants.IGNORE_LABEL,
                                                            IDialogConstants.CANCEL_LABEL }, 0);
                                            boolean ig = dialog.open() == MessageDialog.OK;
                                            if (ig) {
                                                pause = false;
                                                stop = false;
                                            } else {
                                                pause = false;
                                                stop = true;
                                            }
                                        }
                                    });
                                }
                            }
                        }
                        createStatement.close();
                        ok = true;
                    } catch (SQLException e) {
                        msg = substring == null ? e.getMessage() : substring + ":\n\r\r" + e.getMessage();
                        ok = false;
                    } finally {
                        if (createStatement != null) {
                            try {
                                createStatement.close();
                            } catch (SQLException e) {
                                e.printStackTrace();
                            }
                        }
                        manager.closeConnection();
                    }
                    if (!monitor.isCanceled()) {
                        if (!stop) {
                            Display.getDefault().asyncExec(new Runnable() {

                                public void run() {
                                    MessageDialog.openInformation(new Shell(), title, msg);
                                }
                            });
                        } else {
                            ok = false;
                        }
                    }
                    monitor.done();
                }

            });
        } catch (Exception ex) {
            ExceptionOperation.operate(ex);
        }
        return ok;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getCreateSubSQL".
     * 
     * @return
     */
    public String genCreateSysSubscriberSQL() {
        String schema = getSchema();
        String sql = "CREATE TABLE ";
        if (schema != null && !schema.equals("")) {
            sql += schema;
        }
        sql = sql + SYS_TSUBSCRIBERS + "(\n\t" + SYS_TABLE_TO_WATCH + " VARCHAR2(35) NOT NULL,\n\t" + SYS_SUBSCRIBER_NAME
                + " VARCHAR2(50) NOT NULL, \n\t" + SUB_CREATION_DATE + "  DATE NULL, \n\t" + "constraint PK_" + SYS_TSUBSCRIBERS
                + " PRIMARY KEY (" + SYS_TABLE_TO_WATCH + ", " + SYS_SUBSCRIBER_NAME + ")" + ")";
        return sql;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "generateTCDCSQL".
     * 
     * @param table
     * @param dtoW
     * @return
     */
    public String[] genCreateCDCSQL(DBTable table, String dtoW) {
        String[] sql = new String[4];
        String tName = getTableName(table.getName(), TABLE);
        sql[0] = generateInsertData(tName, dtoW);
        sql[1] = generateTCDCTableSQL(table);
        sql[2] = generateTCDCViewSQL(table, dtoW);
        sql[3] = generateTCDCTriggerSQL(table, dtoW);

        return sql;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "generateInsertData".
     * 
     * @param name
     * @param dtoW
     * @return
     */
    private String generateInsertData(String name, String dtoW) {
        String schema = getSchema();
        String sql = "\nINSERT INTO  ";
        if (schema != null && !schema.equals("")) {
            sql += schema;
        }
        sql += SYS_TSUBSCRIBERS;
        sql += " (" + SYS_TABLE_TO_WATCH + "," + SYS_SUBSCRIBER_NAME + "," + SUB_CREATION_DATE + ")";
        sql += " values ('" + dtoW + "','" + name + "',sysdate)";
        return sql;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "generateTCDCTriggerSQL".
     * 
     * @param table
     * @param dtoW
     * @return
     */
    private String generateTCDCTriggerSQL(DBTable table, String dtoW) {
        StringBuilder sql = new StringBuilder("\nCREATE OR REPLACE TRIGGER ");
        sql.append(getTableName(table.getName(), TRIGGER) + "\n");
        sql.append("after INSERT OR UPDATE OR DELETE ON ");
        sql.append(dtoW + "\n");
        sql.append("FOR each row \n");
        sql.append("declare \n");
        sql.append("T_TYPE VARCHAR(1); \n");
        for (String string : varsList) {
            sql.append("T_" + string.trim() + "; \n");
        }
        sql.append("begin \n");
        sql.append("   IF inserting then \n");
        for (String string : this.pkList) {
            sql.append("    T_" + string + " :=:new." + string + ";\n");
        }
        sql.append("    T_TYPE:='I'; \n");
        sql.append("  end IF;\n");

        sql.append("   IF updating then \n");
        for (String string : this.pkList) {
            sql.append("    T_" + string + " :=:new." + string + ";\n");
        }
        sql.append("    T_TYPE:='U'; \n");
        sql.append("  end IF;\n");

        sql.append("   IF deleting then \n");
        for (String string : this.pkList) {
            sql.append("    T_" + string + " :=:old." + string + ";\n");
        }
        sql.append("    T_TYPE:='D'; \n");
        sql.append("  end IF;\n");

        sql.append("  INSERT INTO " + getTableName(table.getName(), TABLE));
        sql.append("  \n(\n");
        sql.append("  " + SUB_NAME);
        sql.append(",\n  " + SUB_STATE);
        sql.append(",\n  " + SUB_TYPE);
        sql.append(",\n  " + SUB_CREATION_DATE);
        for (String string : this.pkList) {
            sql.append(",\n  " + string);
        }
        sql.append("\n)\n   SELECT " + SYS_SUBSCRIBER_NAME);
        sql.append(",\n   '0'");
        sql.append(",\n   T_TYPE");
        sql.append(",\n   sysdate");

        for (String string : this.pkList) {
            sql.append(",\n   T_" + string);
        }
        sql.append("\n  FROM " + getSchema() + SYS_TSUBSCRIBERS);
        sql.append("\n  WHERE " + SYS_TABLE_TO_WATCH + "='" + dtoW + "'; \n" + "end;");

        sql.append("\n" + " --analyze TABLE " + getSchema() + SYS_TSUBSCRIBERS + " compute statistics; ");

        return sql.toString();
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "generateTCDCViewSQL".
     * 
     * @param table
     * @param dtoW
     * @return
     */
    private String generateTCDCViewSQL(DBTable table, String dtoW) {
        String src = getTableName(table.getName(), TABLE);
        StringBuilder sql = new StringBuilder("\nCREATE OR REPLACE VIEW ");
        sql.append(getTableName(table.getName(), VIEW));
        sql.append("\n AS \n SELECT ");
        sql.append("  SRC." + SUB_TYPE + "  " + SUB_TYPE);
        sql.append(",\n  SRC." + SUB_NAME + "  " + SUB_NAME);

        for (String object : pkList) {
            sql.append(",\n  SRC." + object + "  " + object);
        }
        sql.append(",\n  SRC." + SUB_CREATION_DATE + "  " + SUB_CREATION_DATE);
        for (String string : noPKList) {
            sql.append(",\n  TARG." + string + "  " + string);
        }
        sql.append("\nFROM (\n " + "SELECT L." + SUB_TYPE + " " + SUB_TYPE + ", L." + SUB_NAME + "  " + SUB_NAME);
        for (String string : pkList) {
            sql.append(",\n L." + string + "  " + string);
        }
        sql.append(",\n max(L." + SUB_CREATION_DATE + ")  " + SUB_CREATION_DATE + "\n");
        sql.append(" FROM " + src + " L\n");
        sql.append(" Where " + " L." + SUB_STATE + "='1'\n");
        sql.append(" GROUP BY  L." + SUB_TYPE + ", L." + SUB_NAME);
        for (String string : pkList) {
            sql.append(", L." + string);
        }
        sql.append(" ) SRC" + "," + dtoW + " TARG ");
        if (!pkList.isEmpty()) {
            sql.append(" \nWHERE ");
            for (String string : pkList) {
                sql.append("SRC." + string + "=TARG." + string + " (+) AND ");
            }
            for (int i = 0; i < 5; i++) {
                sql.deleteCharAt(sql.length() - 1);
            }
        }
        return sql.toString();
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "generateTCDCTableSQL".
     * 
     * @param table
     * @return
     */
    private String generateTCDCTableSQL(DBTable table) {
        String sql = "\nCREATE TABLE ";
        String tName = getTableName(table.getName(), TABLE);
        sql += tName;
        StringBuilder createSQL = new StringBuilder();
        pkList = new ArrayList<String>();
        varsList = new ArrayList<String>();
        noPKList = new ArrayList<String>();

        String ending = ",";
        int count = 0;
        EList<DBColumn> columns = table.getColumns();
        for (DBColumn column : columns) {
            if (column.isKey()) {
                StringBuilder createSQL2 = new StringBuilder();
                createSQL.append(column.getName() + " ");
                createSQL2.append(column.getName() + " ");
                MetadataTypesManager manager = MetadataTypesManager.getInstance();
                String dataType = null;
                if (column.getType() == null || column.getType().trim().equals("")) {
                    dataType = manager.getDefaultDBTypeLabel();
                } else {
                    dataType = column.getType();
                }
                createSQL.append(dataType);
                createSQL2.append(dataType);

                Integer length = column.getLength();
                Integer precision = column.getPrecision();
                boolean lengthIgnored = manager.isLengthIgnored(dataType);
                boolean precisionIgnored = manager.isPrecisionIgnored(dataType);
                String prefix = "";
                String suffix = "";
                String comma = "";
                if (manager.isPreBeforeLength(dataType)) {
                    if (!precisionIgnored) {
                        prefix = "(";
                        suffix = ") ";
                        createSQL.append(prefix + precision);
                        createSQL2.append(prefix + precision);
                    }
                    if (!lengthIgnored) {
                        prefix = (prefix.equals("") ? "(" : prefix);
                        suffix = (suffix.equals("") ? ") " : suffix);
                        if (precisionIgnored) {
                            createSQL.append(prefix);
                            createSQL2.append(prefix);
                            comma = "";
                        } else {
                            comma = ",";
                        }
                        createSQL.append(comma + length);
                        createSQL2.append(comma + length);
                    }
                    createSQL.append(suffix);
                    createSQL2.append(suffix);
                } else {
                    if (!lengthIgnored) {
                        prefix = "(";
                        suffix = ") ";
                        createSQL.append(prefix + length);
                        createSQL2.append(prefix + length);
                    }
                    if (!precisionIgnored) {
                        prefix = (prefix.equals("") ? "(" : prefix);
                        suffix = (suffix.equals("") ? ") " : suffix);
                        if (lengthIgnored) {
                            createSQL.append(prefix);
                            createSQL2.append(prefix);
                            comma = "";
                        } else {
                            comma = ",";
                        }
                        createSQL.append(comma + precision);
                        createSQL2.append(comma + precision);
                    }
                    createSQL.append(suffix);
                    createSQL2.append(suffix);
                }
                varsList.add(createSQL2.toString());
                createSQL.append(setDefaultValue(column.getDefaultValue(), dataType));
                if (!column.isNullable()) {
                    createSQL.append("not null");
                }
                pkList.add(column.getName());
                count++;
                createSQL.append(ending + "\n");
            } else {
                noPKList.add(column.getName());
            }
        }
        if (count > 0) {
            createSQL.deleteCharAt(createSQL.length() - 1);
            createSQL.insert(0, ending);
        }
        StringBuffer pkStr = new StringBuffer();
        if (pkList.size() > 0) {
            pkStr.append(" constraint PK_");
            pkStr.append(getTNameWithoutSchema(table.getName(), TABLE));
            pkStr.append(" PRIMARY KEY (");
            int i = 0;
            for (String pk : pkList) {
                pkStr.append(pk);
                if (i != pkList.size() - 1) {
                    pkStr.append(",");
                }
                i++;
            }
            pkStr.append(")");
        }
        pkStr.append(")");
        sql += " (" + SUB_NAME + " VARCHAR2(50) NOT NULL, " + SUB_STATE + " VARCHAR2(1) NULL," + " " + SUB_TYPE
                + " VARCHAR2(1) NULL, " + SUB_CREATION_DATE + " DATE NULL" + createSQL.toString() + pkStr.toString();
        return sql;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getTableName".
     * 
     * @param table
     * @param table2
     * @return
     */
    public String getTableName(String table, String table2) {
        String tName = getSchema();
        String tName2 = getTNameWithoutSchema(table, table2);
        tName += tName2;
        return tName;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getSchema".
     * 
     * @return
     */
    private String getSchema() {
        EList<ConnPropertyAttriType> attributes = setType.getAttributes();
        String schema = null;
        for (ConnPropertyAttriType attri : attributes) {
            if (attri.getName().equals(EConnectivityProperties.PROP_ID_SCHEMA.getPropId())) {
                schema = attri.getValue();
                break;
            }

        }
        String tName = "";
        if (schema != null && !schema.equals("")) {
            tName += schema + ".";
        }
        return tName;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getTNameWithoutSchema".
     * 
     * @param table
     * @param tableType
     * @return
     */
    public String getTNameWithoutSchema(String table, String tableType) {
        String tName2 = "";
        if (TABLE.equals(tableType)) {
            tName2 += PREFIX_T;
        } else if (VIEW.equals(tableType)) {
            tName2 += PREFIX_V;
        } else if (TRIGGER.equals(tableType)) {
            tName2 += PREFIX_TG;
        }
        tName2 += table.replaceAll(" ", "_");
        return tName2;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "setDefaultValue".
     * 
     * @param defaultValue
     * @param columnType
     * @return
     */
    private String setDefaultValue(String defaultValue, String columnType) {
        if (defaultValue == null || defaultValue.equals("\"\"") || defaultValue.equals("")) {
            return " ";
        } else if ((defaultValue.startsWith("\"") || defaultValue.startsWith("'"))
                && (defaultValue.endsWith("\"") || defaultValue.endsWith("'"))) {
            return "default '" + defaultValue.substring(1, defaultValue.length() - 1) + "' ";
        } else if (defaultValue.equalsIgnoreCase("null")) {
            return "default null ";
        } else {
            return "default " + defaultValue + " ";
        }
    }

    public String[] genDeleteCDCSQL(DBTable table, String dtoW) {
        String[] sql = new String[4];
        sql[0] = generateDelData(table, dtoW);
        sql[1] = generateDropTrigger(table);
        sql[2] = generateDropView(table);
        sql[3] = generateDropTable(table);
        return sql;
    }

    private String generateDropTable(DBTable table2) {
        String sql = "\n DROP TABLE ";
        sql += getTableName(table2.getName(), TABLE);
        return sql;
    }

    private String generateDropView(DBTable table2) {
        String sql = "\n DROP VIEW ";
        sql += getTableName(table2.getName(), VIEW);
        return sql;
    }

    private String generateDropTrigger(DBTable table2) {
        String sql = "\n DROP TRIGGER ";
        sql += getTableName(table2.getName(), TRIGGER);
        return sql;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "generateDelData".
     * 
     * @param table2
     * @param dtoW
     * @return
     */
    private String generateDelData(DBTable table2, String dtoW) {
        String sql = "\n DELETE FROM ";
        String schema = getSchema();
        if (schema != null && !schema.equals("")) {
            sql += schema;
        }
        sql += SYS_TSUBSCRIBERS;
        sql += " WHERE " + SYS_TABLE_TO_WATCH + "='";
        sql += dtoW + "' AND " + SYS_SUBSCRIBER_NAME + "='" + getTableName(table2.getName(), TABLE) + "'";
        return sql;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getConnName".
     * 
     * @return
     */
    public String getConnName() {
        return setType.getName();
    }

    /**
     * Getter for connId.
     * 
     * @return the connId
     */
    public String getConnId() {
        return this.connId;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "genSysSubscriberEMF".
     * 
     * @return
     */
    public MetadataType genSysSubscriberEMF() {
        WarehouseFactory wfac = DenguesModelManager.getWarehouseFactory();
        MetadataType mtype = wfac.createMetadataType();
        mtype.setName(SYS_TSUBSCRIBERS);
        ColumnType ctype = wfac.createColumnType();
        ctype.setName(SYS_SUBSCRIBER_NAME);
        ctype.setType("VARCHAR2");
        mtype.getColumn().add(ctype);

        ctype = wfac.createColumnType();
        ctype.setName(SYS_TABLE_TO_WATCH);
        ctype.setType("VARCHAR2");
        mtype.getColumn().add(ctype);

        ctype = wfac.createColumnType();
        ctype.setName(SUB_CREATION_DATE);
        ctype.setType("DATE");
        mtype.getColumn().add(ctype);
        return mtype;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "genDelSysSubscriberSQL".
     * 
     * @return
     */
    public String genDelSysSubscriberSQL() {
        String schema = getSchema();
        String sql = "DROP TABLE ";
        if (schema != null && !schema.equals("")) {
            sql += schema;
        }
        sql = sql + SYS_TSUBSCRIBERS;
        return sql;
    }

    /**
     * Getter for setType.
     * 
     * @return the setType
     */
    public ConnPropertySetType getSetType() {
        return this.setType;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "genCreateCDCEMF".
     */
    public void genCreateCDCEMF(DBTable table) {

        CDCConnType cdcConn = getSetType().getCdcConn();
        EList<MetadataType> cdcTables = cdcConn.getCdcTables();
        String tName = getTNameWithoutSchema(table.getName(), TABLE);
        for (MetadataType metaType : cdcTables) {
            if (tName.equals(metaType.getName())) {
                return;
            }
        }
        MetadataType mtype = generateTCDCTableEMF(table);
        cdcTables.add(mtype);

        mtype = generateTCDCViewEMF(table);
        cdcTables.add(mtype);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "generateTCDCViewEMF".
     * 
     * @param table2
     * @return
     */
    private MetadataType generateTCDCViewEMF(DBTable table) {
        WarehouseFactory wfac = DenguesModelManager.getWarehouseFactory();
        MetadataType mtype = wfac.createMetadataType();
        mtype.setName(getTNameWithoutSchema(table.getName(), VIEW));
        createColumns(table, wfac, mtype, true);
        return mtype;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "generateTCDCTableEMF".
     * 
     * @param table
     * @return
     */
    private MetadataType generateTCDCTableEMF(DBTable table) {
        WarehouseFactory wfac = DenguesModelManager.getWarehouseFactory();
        MetadataType mtype = wfac.createMetadataType();
        mtype.setName(getTNameWithoutSchema(table.getName(), TABLE));
        createColumns(table, wfac, mtype, false);
        return mtype;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "createColumns".
     * 
     * @param table
     * @param wfac
     * @param mtype
     * @param b
     */
    private void createColumns(DBTable table, WarehouseFactory wfac, MetadataType mtype, boolean all) {
        ColumnType ctype = wfac.createColumnType();
        ctype.setName(SUB_NAME);
        ctype.setType("VARCHAR2");
        mtype.getColumn().add(ctype);

        ctype = wfac.createColumnType();
        ctype.setName(SUB_CREATION_DATE);
        ctype.setType("DATE");
        mtype.getColumn().add(ctype);

        ctype = wfac.createColumnType();
        ctype.setName(SUB_STATE);
        ctype.setType("VARCHAR2");
        mtype.getColumn().add(ctype);

        ctype = wfac.createColumnType();
        ctype.setName(SUB_TYPE);
        ctype.setType("VARCHAR2");
        mtype.getColumn().add(ctype);

        EList<DBColumn> columns = table.getColumns();
        for (DBColumn column : columns) {
            if (column.isKey()) {
                ctype = wfac.createColumnType();
                ctype.setName(column.getName());
                ctype.setType(column.getType());
                mtype.getColumn().add(ctype);
            } else if (all) {
                ctype = wfac.createColumnType();
                ctype.setName(column.getName());
                ctype.setType(column.getType());
                mtype.getColumn().add(ctype);
            }
        }
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "genDeleteCDCEMF".
     * 
     * @param dataTable
     */
    public void genDeleteCDCEMF(DBTable dataTable) {
        CDCConnType cdcConn = getSetType().getCdcConn();
        EList<MetadataType> cdcTables = cdcConn.getCdcTables();
        List<MetadataType> list = new ArrayList<MetadataType>();
        for (MetadataType mt : cdcTables) {
            String tName = getTNameWithoutSchema(dataTable.getName(), TABLE);
            if (mt.getName().equals(tName)) {
                list.add(mt);
            } else {
                String vName = getTNameWithoutSchema(dataTable.getName(), VIEW);
                if (mt.getName().equals(vName)) {
                    list.add(mt);
                }
            }
        }
        cdcConn.getCdcTables().removeAll(list);
    }
}
